﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Fast.Framework.Models;


namespace Fast.Framework.Extensions
{

    /// <summary>
    /// 表达式扩展类
    /// </summary>
    public static class ExpressionExtensions
    {
        /// <summary>
        /// 解析Sql
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <param name="options">选项</param>
        /// <returns></returns>
        public static SqlInfo ResolveSql(this Expression expression, SqlExpressionOptions options)
        {
            var ex = new SqlExpressionVisitor(options);
            ex.Visit(expression);
            return ex.sqlInfo;
        }
    }

    /// <summary>
    /// 解析类型
    /// </summary>
    public enum ResolveType
    {
        /// <summary>
        /// Sql字符串
        /// </summary>
        SqlString = 0,

        /// <summary>
        /// 调用
        /// </summary>
        Call = 1,

        /// <summary>
        /// 左相似
        /// </summary>
        LeftLike = 2,

        /// <summary>
        /// 右相似
        /// </summary>
        RightLike = 3,

        /// <summary>
        /// 相似
        /// </summary>
        Like = 4
    }

    /// <summary>
    /// 表达式映射
    /// </summary>
    public static class ExpressionMapper
    {
        /// <summary>
        /// 表达式类型
        /// </summary>
        public static readonly Dictionary<ExpressionType, string> expressionTypes;

        /// <summary>
        /// 方法调用
        /// </summary>
        public static readonly Dictionary<string, Action<SqlInfo, MethodCallExpression, Func<Expression, Expression>, Action<ResolveType>>> methodCall;

        /// <summary>
        /// 构造方法
        /// </summary>
        static ExpressionMapper()
        {
            expressionTypes = new Dictionary<ExpressionType, string>()
            {
                {ExpressionType.Add,"+" },
                {ExpressionType.Subtract,"-" },
                {ExpressionType.Multiply,"*" },
                {ExpressionType.Divide,"/" },
                {ExpressionType.AndAlso,"AND" },
                {ExpressionType.OrElse,"OR" },
                {ExpressionType.Equal,"=" },
                {ExpressionType.NotEqual,"<>" },
                {ExpressionType.GreaterThan,">" },
                {ExpressionType.LessThan,"<" },
                {ExpressionType.GreaterThanOrEqual,">=" },
                {ExpressionType.LessThanOrEqual,"<=" }
            };

            methodCall = new Dictionary<string, Action<SqlInfo, MethodCallExpression, Func<Expression, Expression>, Action<ResolveType>>>()
            {
                #region 聚合函数
                {"Sum", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("SUM");
                } },
                {"Max", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("MAX");
                } },
                {"Min", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("MIN");
                } },
                {"Count", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("COUNT");
                } },
                {"Avg", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("AVG");
                } },
                #endregion

                #region 日期函数
                {"GetDate", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("GETDATE");
                } },
                {"Year", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("YEAR");
                } },
                {"Month", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("MONTH");
                } },
                {"Day", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("DAY");
                } },
                {"Current_Timestamp", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("CURRENT_TIMESTAMP");
                } },
                {"Current_Date", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("CURRENT_DATE");
                } },
                {"Current_Time", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("CURRENT_TIME");
                } },
                #endregion

                #region 数学函数
                {"Abs", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("ABS");
                } },
                {"Round", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[1]);
                    sql.SqlStack.Push(",");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("ROUND");
                } },
                #endregion

                #region 字符串函数
                {"Contains", (sql,node,visit,call)=>
                {
                    call(ResolveType.Like);
                    visit.Invoke(node.Arguments[0]);
                    call(ResolveType.SqlString);
                    sql.SqlStack.Push(" LIKE ");
                    visit.Invoke(node.Object);
                } },
                {"StartsWith", (sql,node,visit,call)=>
                {
                    call(ResolveType.LeftLike);
                    visit.Invoke(node.Arguments[0]);
                    call(ResolveType.SqlString);
                    sql.SqlStack.Push(" LIKE ");
                    visit.Invoke(node.Object);
                } },
                {"EndsWith", (sql,node,visit,call)=>
                {
                    call(ResolveType.RightLike);
                    visit.Invoke(node.Arguments[0]);
                    call(ResolveType.SqlString);
                    sql.SqlStack.Push(" LIKE ");
                    visit.Invoke(node.Object);
                } },
                {"Substring", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    if (node.Arguments.Count > 1)
                    {
                        visit.Invoke(node.Arguments[1]);
                        sql.SqlStack.Push(",");
                    }
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push(",");
                    visit.Invoke(node.Object);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("SUBSTRING");
                } },
                {"Replace", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[1]);
                    sql.SqlStack.Push(",");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push(",");
                    visit.Invoke(node.Object);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("REPLACE");
                } },
                {"ToUpper", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Object);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("UPPER");
                } },
                {"ToLower", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Object);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("LOWER");
                } },
                {"Trim", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Object);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("TRIM");
                } },
                #endregion

                #region 其它函数
                {"Equals", (sql,node,visit,call)=>
                {
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push(" = ");
                    visit.Invoke(node.Object);
                } },
                {"IsNull", (sql,node,visit,call)=>
                {
                    sql.SqlStack.Push(")");
                    visit.Invoke(node.Arguments[1]);
                    sql.SqlStack.Push(",");
                    visit.Invoke(node.Arguments[0]);
                    sql.SqlStack.Push("(");
                    sql.SqlStack.Push("ISNULL");
                    visit.Invoke(node.Object);
                } }
	            #endregion
            };
        }
    }

    /// <summary>
    /// Sql表达式访问
    /// </summary>
    public class SqlExpressionVisitor : ExpressionVisitor
    {

        /// <summary>
        /// Sql信息
        /// </summary>
        public readonly SqlInfo sqlInfo;

        /// <summary>
        /// 参数索引
        /// </summary>
        private readonly Dictionary<string, int> parameterIndex;

        /// <summary>
        /// 成员信息
        /// </summary>
        private readonly Stack<MemberInfo> memberInfos;

        /// <summary>
        /// 表达式选项
        /// </summary>
        private readonly SqlExpressionOptions options;

        /// <summary>
        /// 解析类型
        /// </summary>
        private ResolveType resolveType;


        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="options">表达式选项</param>
        public SqlExpressionVisitor(SqlExpressionOptions options, ResolveType resolveType = ResolveType.SqlString)
        {
            sqlInfo = new SqlInfo();
            parameterIndex = new Dictionary<string, int>();
            memberInfos = new Stack<MemberInfo>();
            this.options = options;
            this.resolveType = resolveType;
        }

        /// <summary>
        /// 访问
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        [return: NotNullIfNotNull("node")]
        public override Expression Visit(Expression node)
        {
            //Console.WriteLine(node?.NodeType);
            return base.Visit(node);
        }

        /// <summary>
        /// 访问Lambda
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="node">节点</param>
        /// <returns></returns>
        protected override Expression VisitLambda<T>(Expression<T> node)
        {
            if (!options.IgnoreParameterExpression)
            {
                var index = 0;
                foreach (var parameter in node.Parameters)
                {
                    parameterIndex.Add(parameter.Name, index);
                    index++;
                }
            }
            return Visit(node.Body);
        }

        /// <summary>
        /// 访问一元表达式
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns></returns>
        protected override Expression VisitUnary(UnaryExpression node)
        {
            if (node.NodeType == ExpressionType.ArrayLength)
            {
                var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);
                var array = (sqlExpressionVisitor.Visit(node.Operand) as ConstantExpression).Value as object[];
                return Visit(Expression.Constant(array.Length));
            }
            else if (node.NodeType == ExpressionType.Not)
            {
                if (node.Operand.NodeType == ExpressionType.Call)
                {
                    if (options.DbType == DbType.PostgreSQL)
                    {
                        return Expression.Constant(!Convert.ToBoolean((Visit(node.Operand) as ConstantExpression).Value));
                    }
                    return Expression.Constant(!Convert.ToBoolean((Visit(node.Operand) as ConstantExpression).Value) ? 1 : 0);
                }
                else if (node.Operand.NodeType == ExpressionType.MemberAccess)
                {
                    var memberExpression = node.Operand as MemberExpression;

                    if (memberExpression.Expression.NodeType == ExpressionType.Parameter)
                    {
                        if (options.DbType == DbType.PostgreSQL)
                        {
                            sqlInfo.SqlStack.Push(" = False");
                        }
                        else
                        {
                            sqlInfo.SqlStack.Push(" = 0");
                        }
                        if (memberExpression.Member.IsDefined(typeof(ColumnAttribute)))
                        {
                            sqlInfo.SqlStack.Push(AddIdentifier(memberExpression.Member.GetCustomAttribute<ColumnAttribute>().Name));
                        }
                        else
                        {
                            sqlInfo.SqlStack.Push(AddIdentifier(memberExpression.Member.Name));
                        }
                        return Visit(memberExpression.Expression);
                    }
                    else
                    {
                        memberInfos.Push(memberExpression.Member);
                        var constantExpression = Visit(memberExpression.Expression) as ConstantExpression;
                        return Expression.Constant(!Convert.ToBoolean(constantExpression.Value));
                    }
                }
            }
            return Visit(node.Operand);
        }

        /// <summary>
        /// 访问二元表达式
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns></returns>
        protected override Expression VisitBinary(BinaryExpression node)
        {
            if (node.NodeType == ExpressionType.ArrayIndex)
            {
                var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);
                var array = (sqlExpressionVisitor.Visit(node.Left) as ConstantExpression).Value as object[];
                var value = array[Convert.ToInt32((sqlExpressionVisitor.Visit(node.Right) as ConstantExpression).Value)];
                return VisitConstant(Expression.Constant(value));
            }
            else
            {
                if (!ExpressionMapper.expressionTypes.ContainsKey(node.NodeType))
                {
                    throw new Exception($"暂不支持{node.NodeType}类型解析");
                }

                var op = ExpressionMapper.expressionTypes[node.NodeType];

                bool isBinaryExpression;

                isBinaryExpression = node.Right is BinaryExpression && node.Right.NodeType != ExpressionType.ArrayIndex;

                if (isBinaryExpression)
                {
                    sqlInfo.SqlStack.Push(")");
                }

                if (node.Right.NodeType == ExpressionType.Constant && (node.Right as ConstantExpression).Value == null)
                {
                    if (op == "=")
                    {
                        sqlInfo.SqlStack.Push(" IS NULL");
                    }
                    else if (op == "<>")
                    {
                        sqlInfo.SqlStack.Push(" IS NOT NULL");
                    }
                }
                if (resolveType == ResolveType.SqlString && node.Left.NodeType == ExpressionType.MemberAccess && node.Right.Type.Equals(typeof(bool)))
                {
                    // p.IsOk==true
                    var memberExpression = node.Left as MemberExpression;
                    var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);

                    var constantExpression = sqlExpressionVisitor.Visit(node.Right) as ConstantExpression;

                    if (options.DbType == DbType.PostgreSQL)
                    {
                        sqlInfo.SqlStack.Push(Convert.ToString(Convert.ToBoolean(constantExpression.Value)));
                    }
                    else
                    {
                        sqlInfo.SqlStack.Push(Convert.ToString(Convert.ToBoolean(constantExpression.Value) ? 1 : 0));
                    }

                    sqlInfo.SqlStack.Push(" = ");

                    if (memberExpression.Member.IsDefined(typeof(ColumnAttribute)))
                    {
                        sqlInfo.SqlStack.Push(AddIdentifier(memberExpression.Member.GetCustomAttribute<ColumnAttribute>().Name));
                    }
                    else
                    {
                        sqlInfo.SqlStack.Push(AddIdentifier(memberExpression.Member.Name));
                    }

                    Visit(memberExpression.Expression);
                    return node;
                }
                else
                {
                    Visit(node.Right);
                }

                if (isBinaryExpression)
                {
                    sqlInfo.SqlStack.Push("(");
                }

                sqlInfo.SqlStack.Push($" {op} ");

                isBinaryExpression = node.Left is BinaryExpression && node.Left.NodeType != ExpressionType.ArrayIndex;

                if (isBinaryExpression)
                {
                    sqlInfo.SqlStack.Push(")");
                }

                Visit(node.Left);

                if (isBinaryExpression)
                {
                    sqlInfo.SqlStack.Push("(");
                }
            }
            return node;
        }

        /// <summary>
        /// 访问索引
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns></returns>
        protected override Expression VisitIndex(IndexExpression node)
        {
            return base.VisitIndex(node);
        }

        /// <summary>
        /// 访问参数
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns></returns>
        protected override Expression VisitParameter(ParameterExpression node)
        {
            if (!options.IgnoreParameterExpression)
            {
                sqlInfo.SqlStack.Push($"p{parameterIndex[node.Name]}.");
            }
            return node;
        }

        /// <summary>
        /// 访问对象
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns></returns>
        protected override Expression VisitNew(NewExpression node)
        {
            if (resolveType == ResolveType.SqlString)
            {
                for (int i = 0; i < node.Arguments.Count; i++)
                {
                    var name = AddIdentifier(node.Members[i].IsDefined(typeof(ColumnAttribute)) ? node.Members[i].GetCustomAttribute<ColumnAttribute>().Name : node.Members[i].Name);
                    Visit(node.Arguments[i]);
                    var value = string.Join("", sqlInfo.SqlStack.ToList());
                    sqlInfo.NewKeyValues.Add(name, value);
                    sqlInfo.NewNames.Add(name);
                    sqlInfo.NewValues.Add(value);
                    sqlInfo.NewAssignMapper.Add($"{name} = {value}");
                    sqlInfo.NewAsMapper.Add($"{value} AS {name}");
                    sqlInfo.SqlStack.Clear();
                }
            }
            else if (resolveType == ResolveType.Call)
            {
                var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);

                var args = new List<object>();
                foreach (var item in node.Arguments)
                {
                    args.Add((sqlExpressionVisitor.Visit(item) as ConstantExpression).Value);
                }

                var type = node.Type;

                object obj = null;

                if (type.IsGenericTypeDefinition)//泛型类
                {
                    type = type.MakeGenericType(type.GetGenericArguments());
                }
                if (type.IsDefined(typeof(CompilerGeneratedAttribute)))//匿名对象
                {
                    var argsTypes = args.Select(s => s?.GetType()).ToList().GetTypeDefaultValue();
                    obj = Activator.CreateInstance(type, argsTypes.ToArray());
                    for (int i = 0; i < node.Members.Count; i++)
                    {
                        var member = node.Members[i];
                        type.GetField($"<{member.Name}>i__Field", BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance).SetValue(obj, args[i]);
                    }
                }
                else
                {
                    obj = Activator.CreateInstance(type, args.ToArray());
                }
                return VisitConstant(Expression.Constant(obj));
            }
            return node;
        }

        /// <summary>
        /// 访问列表初始化
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns></returns>
        protected override Expression VisitListInit(ListInitExpression node)
        {
            var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);

            var args = new List<object>();
            args.Add((sqlExpressionVisitor.Visit(node.NewExpression) as ConstantExpression).Value);

            var type = node.Type;
            if (type.IsGenericTypeDefinition)
            {
                type = type.MakeGenericType(type.GetGenericArguments());
            }
            var list = Activator.CreateInstance(type, args.ToArray());
            foreach (var item in node.Initializers)
            {
                var args2 = new List<object>();
                foreach (var item2 in item.Arguments)
                {
                    args2.Add((sqlExpressionVisitor.Visit(item2) as ConstantExpression).Value);
                }
                item.AddMethod.Invoke(list, args2.ToArray());
            }
            if (resolveType == ResolveType.SqlString)
            {
                return VisitConstant(Expression.Constant(string.Join(",", list)));
            }

            return VisitConstant(Expression.Constant(list));
        }

        /// <summary>
        /// 访问数组
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns></returns>
        protected override Expression VisitNewArray(NewArrayExpression node)
        {
            var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);

            int length;
            if (node.NodeType == ExpressionType.NewArrayBounds)
            {
                length = Convert.ToInt32((sqlExpressionVisitor.Visit(node.Expressions[0]) as ConstantExpression).Value);
            }
            else
            {
                length = node.Expressions.Count;
            }

            var array = Array.CreateInstance(node.Type.GetElementType(), length);

            if (node.NodeType == ExpressionType.NewArrayInit)
            {
                for (int i = 0; i < length; i++)
                {
                    array.SetValue((sqlExpressionVisitor.Visit(node.Expressions[i]) as ConstantExpression).Value, i);
                }
            }

            if (resolveType == ResolveType.SqlString)
            {
                return VisitConstant(Expression.Constant(string.Join(",", array as object[])));
            }

            return VisitConstant(Expression.Constant(array));
        }

        /// <summary>
        /// 访问方法
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns></returns>
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (ExpressionMapper.methodCall.ContainsKey(node.Method.Name) && resolveType == ResolveType.SqlString)
            {
                ExpressionMapper.methodCall[node.Method.Name].Invoke(sqlInfo, node, e => Visit(e), (type) =>
                {
                    resolveType = type;//回调设置类型
                });
            }
            else
            {
                var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);
                var args = new List<object>();
                foreach (var item in node.Arguments)
                {
                    args.Add((sqlExpressionVisitor.Visit(item) as ConstantExpression).Value);
                }
                object obj = null;
                if (node.Object == null)
                {
                    obj = this;
                }
                else
                {
                    obj = (sqlExpressionVisitor.Visit(node.Object) as ConstantExpression).Value;
                }
                var value = node.Method.Invoke(obj, args.ToArray());
                resolveType = ResolveType.SqlString;
                return Visit(Expression.Constant(value));
            }
            return node;
        }

        /// <summary>
        /// 访问成员初始化
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        protected override Expression VisitMemberInit(MemberInitExpression node)
        {
            var expressions = (node.Reduce() as BlockExpression).Expressions.Skip(1).SkipLast(1).ToList();//去除不需要的表达式;

            if (resolveType == ResolveType.SqlString)
            {
                for (int i = 0; i < expressions.Count; i++)
                {
                    var binaryExpression = (BinaryExpression)expressions[i];
                    Visit(binaryExpression.Right);
                    var name = AddIdentifier(node.Bindings[i].Member.IsDefined(typeof(ColumnAttribute)) ? node.Bindings[i].Member.GetCustomAttribute<ColumnAttribute>().Name : node.Bindings[i].Member.Name);
                    var value = string.Join("", sqlInfo.SqlStack.ToList());
                    sqlInfo.NewKeyValues.Add(name, value);
                    sqlInfo.NewNames.Add(name);
                    sqlInfo.NewValues.Add(value);
                    sqlInfo.NewAssignMapper.Add($"{name} = {value}");
                    sqlInfo.NewAsMapper.Add($"{value} AS {name}");
                    sqlInfo.SqlStack.Clear();
                }
            }
            var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);
            var obj = (sqlExpressionVisitor.Visit(node.NewExpression) as ConstantExpression).Value;
            for (int i = 0; i < expressions.Count; i++)
            {
                if (node.Bindings[i].Member.MemberType == MemberTypes.Field)
                {
                    var fields = (FieldInfo)node.Bindings[i].Member;
                    fields.SetValue(obj, (sqlExpressionVisitor.Visit((expressions[i] as BinaryExpression).Right) as ConstantExpression).Value);
                }
                if (node.Bindings[i].Member.MemberType == MemberTypes.Property)
                {
                    var propertyInfo = (PropertyInfo)node.Bindings[i].Member;
                    propertyInfo.SetValue(obj, (sqlExpressionVisitor.Visit((expressions[i] as BinaryExpression).Right) as ConstantExpression).Value);
                }
            }
            return VisitConstant(Expression.Constant(obj));
        }

        /// <summary>
        /// 访问成员
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns></returns>
        protected override Expression VisitMember(MemberExpression node)
        {
            if (node.Expression?.NodeType == ExpressionType.Parameter)
            {
                if (memberInfos.Count > 0)
                {
                    throw new Exception($"Parameter 不支持多个属性解析,请将{string.Join(" ", memberInfos.ToList().Select(s => s.Name))}去除,或调用方法");
                }
                if (resolveType == ResolveType.SqlString)
                {
                    if (node.Member.MemberType == MemberTypes.Field)
                    {
                        var fieldInfo = (FieldInfo)node.Member;
                        if (fieldInfo.FieldType.Equals(typeof(bool)))
                        {
                            if (options.DbType == DbType.PostgreSQL)
                            {
                                sqlInfo.SqlStack.Push(" = True");
                            }
                            else
                            {
                                sqlInfo.SqlStack.Push(" = 1");
                            }
                        }
                    }
                    if (node.Member.MemberType == MemberTypes.Property)
                    {
                        var propertyInfo = (PropertyInfo)node.Member;
                        if (propertyInfo.PropertyType.Equals(typeof(bool)))
                        {
                            if (options.DbType == DbType.PostgreSQL)
                            {
                                sqlInfo.SqlStack.Push(" = True");
                            }
                            else
                            {
                                sqlInfo.SqlStack.Push(" = 1");
                            }
                        }
                    }
                }
                if (node.Member.IsDefined(typeof(ColumnAttribute)))
                {
                    sqlInfo.SqlStack.Push(AddIdentifier(node.Member.GetCustomAttribute<ColumnAttribute>().Name));
                }
                else
                {
                    sqlInfo.SqlStack.Push(AddIdentifier(node.Member.Name));
                }
            }
            else
            {
                memberInfos.Push(node.Member);
                if (node.Expression == null && node.NodeType == ExpressionType.MemberAccess)
                {
                    return Visit(Expression.Constant(null));//子表达式为空但有成员处理
                }
            }
            return Visit(node.Expression);
        }

        /// <summary>
        /// 访问常量
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns></returns>
        protected override Expression VisitConstant(ConstantExpression node)
        {
            if (node.Value == null)
            {
                return Expression.Constant(null);
            }
            var value = node.Value;
            foreach (var member in memberInfos)
            {
                if (member.MemberType == MemberTypes.Field)
                {
                    var fieldInfo = (FieldInfo)member;
                    value = fieldInfo.GetValue(value);
                }
                else if (member.MemberType == MemberTypes.Property)
                {
                    var propertyInfo = (PropertyInfo)member;
                    value = propertyInfo.GetValue(value);
                }
            }
            if (resolveType == ResolveType.SqlString && value.GetType().Equals(typeof(bool)))
            {
                if (memberInfos.Count == 0)
                {
                    if (Convert.ToBoolean(value))
                    {
                        sqlInfo.SqlStack.Push("1 = 1");
                    }
                    else
                    {
                        sqlInfo.SqlStack.Push("1 = 0");
                    }
                    return node;
                }
                else if (!options.DbType.Equals(DbType.PostgreSQL))
                {
                    memberInfos.Clear();// bool 类型无需参数化
                    return Expression.Constant(Convert.ToBoolean(value) ? 1 : 0);
                }
            }
            if (resolveType != ResolveType.Call)
            {
                if (value != null && value.GetType().Equals(typeof(DateTime)))
                {
                    value = Convert.ToDateTime(value).ToString(options.DateTimeFormat);//格式化日期类型
                }
                if (memberInfos.Count > 0)
                {
                    var parameterName = Guid.NewGuid().ToString().Replace("-", "");
                    sqlInfo.SqlStack.Push($"{DbSymbolMapper.parameter[options.DbType]}{parameterName}");
                    sqlInfo.SqlParameters.Add(parameterName, AddWildcard(value));
                }
                else
                {
                    value = AddQuotes(AddWildcard(value));
                    sqlInfo.SqlStack.Push(Convert.ToString(value));
                }
            }

            //最后一个节点初始化
            memberInfos.Clear();
            return Expression.Constant(value);//返回新的常量表达式
        }

        #region 私有公共方法

        /// <summary>
        /// 添加引号
        /// </summary>
        /// <param name="value">值</param>
        /// <returns></returns>
        private static object AddQuotes(object value)
        {
            if (value == null)
            {
                return null;
            }
            var type = value.GetType();
            if (type.Equals(typeof(char)) || type.Equals(typeof(string)) || type.Equals(typeof(DateTime)))
            {
                return $"'{value}'";
            }
            return value;
        }

        /// <summary>
        /// 添加识别符
        /// </summary>
        /// <param name="name">名称</param>
        /// <returns></returns>
        private string AddIdentifier(string name)
        {
            return DbSymbolMapper.identify[options.DbType].Insert(1, name);
        }

        /// <summary>
        /// 添加通配符
        /// </summary>
        /// <param name="value">值</param>
        /// <returns></returns>
        private object AddWildcard(object value)
        {
            if (resolveType == ResolveType.LeftLike)
            {
                return $"%{value}";
            }
            else if (resolveType == ResolveType.RightLike)
            {
                return $"{value}%";
            }
            else if (resolveType == ResolveType.Like)
            {
                return $"%{value}%";
            }
            return value;
        }
        #endregion

    }
}
